const compiler = function compiler(){
    console.log('数据改变,更新视图')
}
const isArray = Array.isArray
const isObject = (val) => val !== null && typeof val === "object"
const hasOwn = (val,key) => val.hasOwnProperty(key)

function toRaw(observed){
    const raw = observed && observed["__v_raw"]
    return raw ? toRaw(raw) : observed
}

function createArrayInstrumentations(){
    const instrumentations = {};
    ['includes','indexOf','lastIndexOf'].forEach(key => {
        instrumentations[key] = function (...args){
            const arr = toRaw(this)
            const res = arr[key](...args)
            if(res === -1 || res === false){
                return arr[key](...args.map(toRaw))
            }else{
                return res
            }
        }
    })
    ;['push','pop','shift','unshift','splice'].forEach(key => {
        instrumentations[key] = function (...args){
            const res = toRaw(this)[key].apply(this,args)
            console.log('数组方法执行')
            compiler()
            return res
        }
    })
    return instrumentations
}

const arrayInstrumentations = createArrayInstrumentations()

const mutableHandlers = {
    get:function get(target,key){
        //如果操作的是数组中的方法去修改
        const targetIsArray = isArray(target)
        if(targetIsArray && hasOwn(arrayInstrumentations,key)){
            return Reflect.get(arrayInstrumentations,key)
        }

        const res = Reflect.get(target,key)
        if(isObject(res)){
            //在访问某个成员时,发现此成员是一个对象,再做劫持,返回新代理劫持后的对象[递归]
            return reactive(res)
        }
        console.log('get执行')
        return res
    },
    set:function set(target,key,value){
        const res = Reflect.set(target,key,value)
        console.log('set执行')
        compiler()
        return  res
    },
    deleteProperty:function deleteProperty(target,key){
        const res = Reflect.deleteProperty(target,key)
        console.log('delete执行')
        compiler()
        return  res
    },
    has:function has$1(target,key){
        const res = Reflect.has(target,key)
        console.log('has执行')
        compiler()
        return  res
    },
    ownKeys:function ownKeys(target){
        console.log('ownKeys执行')
        return Reflect.ownKeys(target)
    }
}

const proxyMap = new WeakMap()
function createReactiveObject(target,baseHandlers){
    if(!isObject(target)){
        console.log(`该数据无法做响应式处理:${String(target)}`)
        return target
    }
    //经过劫持过的就不再重复劫持了
    const existingProxy = proxyMap.get(target)
    if(existingProxy){
        return existingProxy
    }
    //没处理过的进行劫持
    const proxy = new Proxy(target,baseHandlers)
    proxyMap.set(target,proxy)
    return proxy
}

function reactive(target){
    return createReactiveObject(target,mutableHandlers);
}

let data = {
    num:200,
    str:'响应式测试数据',
    arr:[10,20,[30,40],{a:'A',b:'B'}],
    obj:{x:10,y:{z:20},m:[100,200]},
}

reactive(data)

let state = reactive(data)

window.state = state
